'''
* This is the projet for Brtc LlmOps Platform
* @Author Leon-liao <liaosiliang@alltman.com>
* @Description //TODO 
* @File: openapi_schema.py
* @Time: 2025/9/23
* @All Rights Reserve By Brtc
'''
from enum import Enum

from pydantic import BaseModel, Field, field_validator
from internal.exception.exception import ValidateErrorException

class ParameterType(str, Enum):
    """参数支持类型"""
    STR = "str"
    INT= "int"
    FLOAT = "float"
    BOOL="bool"

ParameterTypeMap={
    ParameterType.STR: str,
    ParameterType.INT: int,
    ParameterType.FLOAT: float,
    ParameterType.BOOL: bool,
}

class ParameterIn(str, Enum):
    """参数支持存放的位置"""
    PATH= "path"
    QUERY= "query"
    HEADER= "header"
    COOKIE= "cookie"
    REQUEST_BODY= "request_body"


class OpenAPISchema(BaseModel):
    """OpenAPI的数据规范结构"""
    server:str= Field(default="", validate_default=True, description="工具提供者服务基础地址")
    description:str = Field(default="", validate_default=True, description="工具提供商的描述信息")
    paths:dict[str, dict] = Field(default_factory=dict, validate_default=True, description="工具提供商路径参数字典")

    @field_validator("server", mode="before")
    def validate_server(cls, server: str) -> str:
        """校验sever数据"""
        if server is None or server == "":
            raise ValidateErrorException("server 字段不能为空,且为字符串。")
        return server

    @field_validator("description", mode="before")
    def validate_description(cls, description: str) -> str:
        """校验description数据"""
        if description is None or description == "":
            raise ValidateErrorException("description 字段不能为空,且为字符串。")
        return description

    @field_validator("paths", mode="before")
    def validate_paths(cls, paths: dict[str, dict]) ->dict[str, dict]:
        """校验paths信息，包含方法提取、 operationId唯一标识、parameters校验"""
        #1、paths 不能为空，且为字典
        if not paths or not isinstance(paths, dict):
            raise ValidateErrorException("openapi_schema的paths 字段不能为空且必须是字典类型")
        #2、提取paths 中的每个元素并获取方法 get&post
        methods = ["get", "post"]
        interfaces=[]
        extra_paths = {}
        for path, path_item in paths.items():
            for method in methods:
                #3、检测是否存在特定的方法并提取信息
                if method in path_item:
                    interfaces.append({
                        "path":path,
                        "method":method,
                        "operation":path_item[method]
                    })
        #4、遍历提取到所有接口并校验信息，涵盖operationId唯一标识， parameters参数
        operation_ids = []
        for interface in interfaces:
            #5、校验description&operationId&parameter字段
            if not isinstance(interface["operation"].get("description"), str):
                raise ValidateErrorException("description 不能为空且为字符串！")
            if not isinstance(interface["operation"].get("operationId"), str):
                raise ValidateErrorException("operationId 不能为空且为字符串！")
            if not isinstance(interface["operation"].get("parameters",[]), list):
                raise ValidateErrorException("parameters 必须为列表且不为空！")
            #6、检测operationId 是否为唯一
            if interface["operation"]["operationId"] in operation_ids:
                raise ValidateErrorException(f"operationId 必须唯一, {interface['operation']['operationId']} 出现了重复！")

            operation_ids.append(interface["operation"]["operationId"])

            #7、检验parameters 格式是否正确
            for parameter in interface["operation"].get("parameters",[]):
                #8、检验 name / in / description / required / type 参数是否存在， 并且类型正确
                if not isinstance(parameter.get("name"), str):
                    raise ValidateErrorException("parameter.name 必须为字符串且不为空！")
                if not isinstance(parameter.get("description"), str):
                    raise ValidateErrorException("parameter.description 必须为字符串且不为空！")
                if not isinstance(parameter.get("required"), bool):
                    raise ValidateErrorException("parameter.required 必须为字符串且不为空！")

                if not isinstance(parameter.get("in"), str) or parameter.get("in") not in ParameterIn.__members__.values():
                    raise ValidateErrorException(f"parameter.in 参数必须为{'/'.join([item.value for item in ParameterIn])}")

                if not isinstance(parameter.get("type"), str) or parameter.get("type") not in ParameterType.__members__.values():
                    raise ValidateErrorException(f"parameter.type 参数必须为{'/'.join([item.value for item in ParameterType])}")
            #9、组装数据并更新
            extra_paths[interface["path"]] = {
                interface["method"]:{
                    "description":interface["operation"]["description"],
                    "operationId":interface["operation"]["operationId"],
                    "parameters":[{
                        "name":parameter.get("name"),
                        "in":parameter.get("in"),
                        "description":parameter.get("description"),
                        "required":parameter.get("required"),
                        "type":parameter.get("type"),
                    } for parameter in interface["operation"].get("parameters",[])]
                }
            }
        return extra_paths









